import React from 'react'
import Component, { mapStateToProps, mapDispatchToProps } from '../components/Component'
import { connect } from 'react-redux'
import { Document, Page } from 'react-pdf'
// import { Document, Page } from 'react-pdf/dist/entry.webpack'
import moment from 'moment'
import { message, Form, Input, Select, DatePicker, Button, Space, Skeleton, Dropdown } from 'antd'
import { addResizeEvent, delResizeEvent } from '../redux/actions'
import { DownOutlined } from '@ant-design/icons'
import FreeScrollBar from 'react-free-scrollbar'
import style from './PdfReader.module.less'
import { confirmAction } from '@js/tool'
import { download } from '@js/downloadRename'
import { encode } from 'js-base64'
// pdfjs.GlobalWorkerOptions.workerSrc = `//${location.host}/pdf.worker.js`
const { Item } = Form
const { TextArea } = Input
const { Option } = Select
class Text extends React.Component {
  render () {
    return <span>{this.props.value || '暂无'}</span>
  }
}

class PdfReader extends Component {
  state = {
    file: null,
    isSeal: false,
    tempSeal: null,
    formParamsHidden: [], // 表单隐藏的参数列表
    formParams: [], // 表单参数列表
    formParamsMap: {}, // 表单参数对象
    formInitData: {}, // 表单初始值
    width: 0,
    height: 0,
    numPages: 0,
    ready: false,
    timer: null
  }

  docBoxRef = React.createRef()
  formRef = React.createRef()

  initState () {
    this.setState({
      file: null,
      isSeal: false,
      tempSeal: null,
      formParamsHidden: [], // 表单隐藏的参数列表
      formParams: [], // 表单参数列表
      formParamsMap: {}, // 表单参数对象
      formInitData: {}, // 表单初始值
      numPages: 0
    })
  }

  // 根据id获取文书
  getFileById () {
    const { caseid, fileid } = this.props.meta
    return this.$get(`/api/vendor/case/file/${caseid}/${fileid}`)
      .then(res => {
        if (res.status !== 1) {
          return message.warning(res.message)
        }
        this.initState()
        const file = res.data
        if (!file.pdf_path) {
          this.setState({
            timer: setTimeout(() => {
              this.getFileById()
            }, 2000)
          })
          return false
        }
        this.state.timer && clearTimeout(this.state.timer)
        file.pdf_path = file.pdf_path.replace(/^.*\/upload/, '/upload')
        this.setState({
          file,
          isSeal: Boolean(file.seal),
          tempSeal: file.temp_seal
        }, () => {
          this.initFormParamsData()
        })
      }).catch(() => {})
  }

  // 根据文书参数和文书模板参数生成表单参数
  initFormParamsData () {
    window.moment = moment
    const formInitData = {}
    const formParamsMap = {}
    const formParamsHidden = (this.state.file.parameters || []).filter(li => li.parm_input_type === '隐藏域')
    const formParams = (this.state.file.parameters || []).filter(li => li.parm_input_type !== '隐藏域').map(li => {
      const v = li.parm_value
      const t = li.parm_input_type
      const k = li.parm_key
      const td = li.parm_type_data
      if (t === '多选选择器' && v) {
        formInitData[k] = v.split(',').filter(li => li !== '')
      } else if (t === '时间选择器' && v) {
        let filterV = encodeURIComponent(li.parm_value)
        filterV = filterV.replace(/%C2%A0/g, '%20')
        filterV = decodeURIComponent(filterV)
        formInitData[k] = moment(filterV, td || 'YYYY年MM月DD日')
      } else {
        formInitData[k] = v
      }
      formParamsMap[k] = li

      return li
    })
    this.setState({
      formParamsHidden,
      formParams,
      formInitData,
      formParamsMap
    }, () => {
      if (!this.props.meta.readonly) {
        this.formRef.current.resetFields()
      }
    })
  }

  // 初始化文件参数
  initDoc (o) {
    const width = this.docBoxRef.current.offsetWidth
    this.setState({
      numPages: o.numPages,
      ready: true,
      width,
      height: width * 1.4140625
    })
  }

  // 设置pdf宽度
  setPdfWidth () {
    if (this.docBoxRef.current) {
      const width = this.docBoxRef.current.offsetWidth
      this.setState({
        ready: false
      }, () => {
        setTimeout(() => {
          this.setState({
            ready: true,
            width: width - 40,
            height: width * 1.4140625
          })
        }, 200)
      })
    }
  }

  // 更新文档参数请求
  updateRequest (parameters, seal = undefined) {
    const hide = message.loading('生成中', 120)
    const { caseid, fileid } = this.props.meta
    const b = encode(JSON.stringify(parameters))
    this.$put(`/api/vendor/case/file/${caseid}/${fileid}`, {
      parameters: b,
      seal
    }).then(res => {
      hide()
      if (res.status === 1) {
        this.setState({
          file: null
        })
        message.success('生成成功')
        this.getFileById()
      } else {
        message.warning(res.message)
      }
    }).catch(() => hide())
  }

  // 重新生成
  reCreateHandle (v) {
    const parameters = this.formatFormData(v)
    this.updateRequest(parameters)
  }

  // 根据盖章与否重新生成文档
  reCreateByChangeSeal () {
    const { file, tempSeal, isSeal } = this.state
    const parameters = file.parameters.map(li => {
      return {
        id: li.id,
        parm_key: li.parm_key,
        parm_value: li.parm_value
      }
    })
    this.updateRequest(parameters, isSeal ? null : tempSeal)
  }

  // 格式化表单值
  formatFormData (v) {
    const { formParamsMap, formParamsHidden } = this.state
    const keys = Object.keys(v)
    const result = []
    keys.forEach(key => {
      const o = formParamsMap[key] || {}
      let value = v[key] === undefined ? '' : v[key]
      if (value instanceof Array) {
        value = value.join(',')
      } else if (value instanceof moment) {
        value = value.format(o.parm_type_data || 'YYYY年MM月DD日')
      }
      result.push({
        id: o.id,
        parm_key: o.parm_key,
        parm_value: value
      })
    })
    formParamsHidden.forEach(li => {
      result.push({
        id: li.id,
        parm_key: li.parm_key,
        parm_value: li.parm_value
      })
    })
    return result
  }

  // 根据最新案件数据重新生成文书
  reproduceDoc () {
    const hide = message.loading('重置文书中', 120)
    const { fileid } = this.props.meta
    this.$post('/api/vendor/case/regenerate_file', {
      id: fileid
    }).then(res => {
      hide()
      if (res.status === 1) {
        this.setState({
          file: null
        })
        message.success('重置成功')
        this.getFileById()
      } else {
        message.warning(res.message)
      }
    }).catch(() => hide())
  }

  componentDidMount () {
    this.getFileById()
    this.setPdfWidth()
    this.props.addResizeEvent({ name: `resizePdf-${this.props.meta.fileid}`, handle: () => this.setPdfWidth() })
    setTimeout(() => {
      const c = this.docBoxRef.current || {}
      this.setState({
        width: c.offsetWidth,
        height: c.offsetHeight
      })
    }, 200)
  }

  componentWillUnmount () {
    this.state.timer && clearTimeout(this.state.timer)
    this.props.delResizeEvent(`resizePdf-${this.props.meta.fileid}`)
  }

  // 渲染pdf页面
  renderPages () {
    if (this.state.ready) {
      const arr = []
      for (let i = 0; i < this.state.numPages; i++) {
        arr.push((
          <div className={style.page} key={i}>
            <Page pageNumber={i + 1} width={this.state.width} height={this.state.height} renderTextLayer={false} renderAnnotationLayer={false} />
          </div>
        ))
      }
      return arr
    }
  }

  // 渲染pdf参数列表
  renderParams () {
    return (
      <Form layout='vertical' initialValues={this.state.formInitData} ref={this.formRef} onFinish={v => this.reCreateHandle(v)}>
        {
          this.state.formParams.map((li, i) => {
            return (
              <Item key={li.id} name={li.parm_key} label={`${i + 1}. ${li.parm_key}`}>
                {this.renderItemInput(li)}
              </Item>
            )
          })
        }
      </Form>
    )
  }

  // 渲染表单输入框
  renderItemInput (data) {
    let options = []
    if (data.parm_type_data) {
      options = data.parm_type_data
    }
    switch (data.parm_input_type) {
      case '文本框':
        return (<Input placeholder='请输入' />)
      case '文本域':
        return (<TextArea placeholder='请输入' />)
      case '单选选择器':
        return (
          <Select placeholder='请选择'>
            {
              options.map((li, i) => (
                <Option key={i} value={li.value}>{li.title}</Option>
              ))
            }
          </Select>
        )
      case '多选选择器':
        return (
          <Select placeholder='请选择' mode='multiple'>
            {
              options.map((li, i) => (
                <Option key={i} value={li.value}>{li.title}</Option>
              ))
            }
          </Select>
        )
      case '时间选择器':
        return (<DatePicker className={style.full} placeholder='请选择' />)
      default:
        return (<Text />)
    }
  }

  renderLoading () {
    return (
      <div className={style['empty-page']}>
        <Skeleton active paragraph={{ rows: 6 }} />
      </div>
    )
  }

  renderEditorPart () {
    const { file } = this.state
    const canSave = file && file.parameters && file.parameters.length
    const { isSeal, tempSeal } = this.state
    if (this.props.meta.readonly) {
      return null
    }
    const menu = []
    if (canSave) {
      menu.push({ label: '重新生成', key: 0, onClick: () => confirmAction('本操作会根据参数设置的最新内容，重新生产文书，您确定要执行本操作吗？', () => this.formRef.current.submit()) })
      menu.push({ label: '重置文书', key: 4, onClick: () => confirmAction('本操作会重新抓取最新案件数据，重新生成文书，您确定要执行本操作吗？', () => { this.reproduceDoc() }) })
    }
    if (this.state.file) {
      menu.push({
        label: '下载pdf',
        key: 1,
        onClick: () => {
          const { original_filename: s, pdf_path: p } = this.state.file
          download(p, `${s}.pdf`)
        }
      })
      menu.push({
        label: '下载docx',
        key: 2,
        onClick: () => {
          const { original_filename: s, docx_path: p } = this.state.file
          download(p, `${s}.docx`)
        }
      })
    }
    if (tempSeal) {
      menu.push({ label: isSeal ? '不带印章pdf' : '带印章pdf', key: 3, onClick: () => { this.reCreateByChangeSeal() } })
    }
    return (
      <div className={style['right-box']}>
        <div className={style['right-box-inner']}>
          {file ? (
            <div className={style['btn-blocks']}>
              <div className={style['btn-line']}>
                <Space>
                  <Button disabled={this.state._printing} className={style['bg-white']} type='primary' ghost onClick={() => this.$print(this.state.file.pdf_path)}>打印</Button>
                  <Dropdown menu={{ items: menu }} trigger={['click']}>
                    <Button>
                      更多操作 <DownOutlined />
                    </Button>
                  </Dropdown>
                </Space>
              </div>
            </div>
          ) : null}
          {canSave ? <div className={style['right-box-title']}>参数设置</div> : null}
          <div className={style['right-box-params']}>
            <FreeScrollBar className='mock' autohide={false}>
              <div className={style['right-box-params-list']}>
                {this.renderParams()}
              </div>
            </FreeScrollBar>
          </div>
        </div>
      </div>
    )
  }

  render () {
    return (
      <div className={style.container}>
        <div className={style.inner}>
          <div className={style['left-box']}>
            <div className={style['pdf-box']} ref={this.docBoxRef}>
              {
                this.state.file ? (
                  <Document
                    loading={this.renderLoading()}
                    file={`${this.state.file.pdf_path}`}
                    onLoadSuccess={e => this.initDoc(e)}
                    error='文书生成失败，请点击“重新生成”操作。'
                    // options={{ cMapUrl: 'cmaps/', cMapPacked: true }}
                  >
                    {this.renderPages()}
                  </Document>
                ) : this.renderLoading()
              }
            </div>
          </div>
          {this.renderEditorPart()}
        </div>
      </div>
    )
  }
}

const mapState = mapStateToProps(function (state) {
  return {
    userInfo: state.basic.userInfo
  }
})

const mapDispatch = mapDispatchToProps(function (dispatch) {
  return {
    addResizeEvent: i => dispatch(addResizeEvent(i)),
    delResizeEvent: i => dispatch(delResizeEvent(i))
  }
})

export default connect(mapState, mapDispatch)(PdfReader)
